package club.xyes.zkh.ecommerce.web.api.controller;

import club.xyes.zkh.ecommerce.commons.dto.MinimalUserInfo;
import club.xyes.zkh.ecommerce.commons.entity.*;
import club.xyes.zkh.ecommerce.commons.properties.WebsiteConfigurationProperties;
import club.xyes.zkh.ecommerce.commons.util.CouponUtils;
import club.xyes.zkh.ecommerce.commons.util.EntityImagePathUtils;
import club.xyes.zkh.ecommerce.commons.vo.GeneralCollectionResult;
import club.xyes.zkh.ecommerce.commons.vo.GeneralResult;
import club.xyes.zkh.ecommerce.service.*;
import club.xyes.zkh.ecommerce.service.listener.OnCouponGrantListener;
import club.xyes.zkh.ecommerce.web.api.vo.CouponGroupGrantParam;
import club.xyes.zkh.ecommerce.web.controller.BaseController;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Create by 郭文梁 2019/4/18 0018 13:45
 * UserCouponController
 * 用户优惠券关系相关数据访问控制器
 *
 * @author 郭文梁
 * @data 2019/4/18 0018
 */
@RestController
@RequestMapping("/api/user-coupon")
@Slf4j
public class UserCouponController extends BaseController<UserCoupon> {
    private final UserCouponService service;
    private final UserMembershipService userMembershipService;
    private final ShopService shopService;
    private final UserService userService;
    private final CouponService couponService;
    private final WebsiteConfigurationProperties websiteConfigurationProperties;
    private final OnCouponGrantListener onCouponGrantListener;

    @Autowired
    public UserCouponController(UserCouponService service,
                                UserMembershipService userMembershipService,
                                ShopService shopService,
                                UserService userService,
                                CouponService couponService,
                                WebsiteConfigurationProperties websiteConfigurationProperties,
                                OnCouponGrantListener onCouponGrantListener) {
        super(service);
        this.service = service;
        this.userMembershipService = userMembershipService;
        this.shopService = shopService;
        this.userService = userService;
        this.couponService = couponService;
        this.websiteConfigurationProperties = websiteConfigurationProperties;
        this.onCouponGrantListener = onCouponGrantListener;
    }

    /**
     * 获取当前用户可用的优惠券
     *
     * @return GeneralCollectionResult
     */
    @GetMapping("/mine")
    @ApiOperation("获取当前用户拥有的优惠券")
    public GeneralCollectionResult<UserCoupon> mine() {
        @NotNull MinimalUserInfo userInfo = getRequiredUserInfo();
        List<UserCoupon> couponList = service.findByUserIdFetchAll(userInfo.getUserId());
        couponList = couponList.stream()
                .filter(uc -> CouponUtils.checkAvailable(uc.getCoupon()))
                .collect(Collectors.toList());
        couponList = prettyPath(couponList);
        return GeneralCollectionResult.ok(couponList);
    }

    /**
     * 获取可用的优惠券
     *
     * @param shopId 商铺ID
     * @return GCR
     */
    @GetMapping("/available/shop/{shopId}")
    @ApiOperation("获取可用的优惠券")
    public GeneralCollectionResult<UserCoupon> available(@PathVariable("shopId") Integer shopId,
                                                         @RequestParam("totalFee") Integer totalFee,
                                                         @RequestParam("noDiscountAmount") Integer noDiscountAmount) {
        Shop shop = shopService.getRequired(shopId);
        User user = userService.getRequired(getRequiredUserInfo().getUserId());
        List<UserCoupon> coupons = service.available(user, shop,
                totalFee - noDiscountAmount,
                userMembershipService.isMembership(user, shop));
        coupons = prettyPath(coupons);
        return GeneralCollectionResult.ok(coupons);
    }

    /**
     * 查询当前用户所拥有指定商家的优惠券
     *
     * @param shopId 商家ID
     * @return UserCoupon
     */
    @GetMapping("/mine/shop/{shopId}")
    @ApiOperation("查询当前用户所拥有指定商家的优惠券")
    public GeneralCollectionResult<UserCoupon> findByShopId(@PathVariable("shopId") Integer shopId) {
        User user = userService.getRequired(getRequiredUserInfo().getUserId());
        Shop shop = shopService.getRequired(shopId);
        List<UserCoupon> userCoupons = service.findByUserAndShop(user, shop);
        userCoupons = prettyPath(userCoupons);
        return GeneralCollectionResult.ok(userCoupons);
    }

    /**
     * 用户领取优惠券
     *
     * @param param {couponId: 1}
     * @return GR
     */
    @ApiOperation("用户领取优惠券")
    @PostMapping("/take")
    public GeneralResult<UserCoupon> take(@RequestBody UserCoupon param) {
        if (param == null || param.getCouponId() == null) {
            return GeneralResult.badRequest("缺少参数");
        }
        Integer couponId = param.getCouponId();
        Coupon coupon = couponService.getRequired(couponId);
        User user = userService.getRequired(getRequiredUserInfo().getUserId());
        UserCoupon res = service.take(user, coupon);
        prettyPath(res);
        return GeneralResult.ok(res);
    }

    /**
     * 设置路径为绝对路径
     *
     * @param userCoupons 用户优惠券
     * @return UserCoupon list
     */
    private List<UserCoupon> prettyPath(List<UserCoupon> userCoupons) {
        return userCoupons.stream()
                .peek(uc -> EntityImagePathUtils.prettyCouponImagePath(
                        uc.getCoupon(),
                        websiteConfigurationProperties.getStaticServerPrefix(),
                        websiteConfigurationProperties.getCouponImagePath()))
                .collect(Collectors.toList());
    }

    /**
     * 设置路径为绝对路径
     *
     * @param userCoupon 用户优惠券
     */
    private void prettyPath(UserCoupon userCoupon) {
        EntityImagePathUtils.prettyCouponImagePath(
                userCoupon.getCoupon(),
                websiteConfigurationProperties.getStaticServerPrefix(),
                websiteConfigurationProperties.getCouponImagePath());
    }

    /**
     * 店铺可用的优惠信息
     *
     * @param shopId 店铺ID
     * @return GR
     */
    @ApiOperation("店铺可用优惠信息")
    @GetMapping("/shop/{shopId}/offers")
    public GeneralResult<Map<String, Object>> offers(@PathVariable("shopId") Integer shopId) {
        Shop shop = shopService.getRequired(shopId);
        User user = userService.getRequired(getRequiredUserInfo().getUserId());
        Map<String, Object> preferentialWay = getPreferentialWayByShopAndUser(shop, user);
        return GeneralResult.ok(preferentialWay);
    }

    /**
     * 获取商户的优惠途径信息
     *
     * @param sn SN
     * @return GR
     */
    @GetMapping("/shop/{sn}/preferential-way")
    public GeneralResult<Map<String, Object>> offers(@PathVariable("sn") String sn) {
        Shop shop = shopService.findBySn(sn);
        if (shop == null) {
            return GeneralResult.badRequest("商铺不存在");
        }
        User user = currentUser(userService);
        Map<String, Object> preferentialWay = getPreferentialWayByShopAndUser(shop, user);
        return GeneralResult.ok(preferentialWay);
    }

    /**
     * 通过商铺和用户获取商铺的优惠途径
     *
     * @param shop 商铺
     * @param user 用户
     * @return 优惠途径信息
     */
    private Map<String, Object> getPreferentialWayByShopAndUser(Shop shop, User user) {
        prettyPath(shop);
        List<UserCoupon> coupons = service.findByUserAndShop(user, shop);
        coupons = prettyPath(coupons);
        List<UserMembership> memberships = userMembershipService.findByUserIdAndShopIdFetchAll(user.getId(), shop.getId());
        memberships = prettyMembershipPath(memberships);
        Map<String, Object> res = new HashMap<>(3);
        res.put("coupons", coupons);
        res.put("memberships", memberships);
        res.put("shop", shop);
        return res;
    }

    /**
     * 替换路径
     *
     * @param memberships 会员信息
     * @return 替换结果
     */
    private List<UserMembership> prettyMembershipPath(List<UserMembership> memberships) {
        String serverPrefix = websiteConfigurationProperties.getStaticServerPrefix();
        String imagePath = websiteConfigurationProperties.getShopMembershipImagePath();
        String shopLogoPath = websiteConfigurationProperties.getShopLogoPath();
        return memberships.stream()
                .peek(membership -> {
                    EntityImagePathUtils.prettyShopMembershipImagePath(membership.getLevel().getMembership(), serverPrefix, imagePath);
                    EntityImagePathUtils.prettyLogoPath(membership.getLevel().getMembership().getShop(), serverPrefix, shopLogoPath);
                }).collect(Collectors.toList());
    }

    /**
     * 发放优惠券
     *
     * @param userId   用户ID
     * @param couponId 优惠券ID
     * @return GR
     */
    @PostMapping("/grant")
    @ApiOperation("发放优惠券")
    public GeneralResult<UserCoupon> grant(@RequestParam("userId") Integer userId,
                                           @RequestParam("couponId") Integer couponId) {
        User user = userService.getRequired(userId);
        Coupon coupon = couponService.getRequired(couponId);
        UserCoupon userCoupon = new UserCoupon();
        userCoupon.setUserId(userId);
        userCoupon.setUser(user);
        userCoupon.setCouponId(couponId);
        userCoupon.setCoupon(coupon);
        userCoupon.setStatus(UserCoupon.STATUS_ENABLE);
        UserCoupon res = service.save(userCoupon);
        return GeneralResult.ok(res);
    }

    /**
     * 群发优惠券
     *
     * @param couponId 优惠券ID
     * @param param    {userIdList:[]}
     * @return GR
     */
    @PostMapping("/{couponId}/group-grant")
    @ApiOperation("群发优惠券接口")
    public GeneralResult<?> groupGrant(@PathVariable("couponId") Integer couponId,
                                       @RequestBody CouponGroupGrantParam param) {
        if (param == null || param.getUserIdList() == null || param.getUserIdList().size() <= 0) {
            return GeneralResult.badRequest("参数不完整");
        }
        Coupon coupon = couponService.getRequired(couponId);
        Shop shop = currentShop(shopService);
        if (!Objects.equals(shop.getId(), coupon.getShopId())) {
            return GeneralResult.badRequest("无权操作该数据");
        }
        List<User> users = userService.findByIds(param.getUserIdList());
        List<UserCoupon> couponList = service.grant(coupon, shop, param.getUserIdList(), users, onCouponGrantListener);
        return GeneralResult.ok(couponList);
    }

    /**
     * 替换商铺图片路径
     *
     * @param shop 商铺
     */
    private void prettyPath(Shop shop) {
        prettyPath(websiteConfigurationProperties, shop);
    }
}
